package com.da.auth.service.impl;

import com.da.auth.entity.constant.DailyAuthConstant;

import com.da.common.constant.DailyConstant;
import com.da.common.entity.PageResult;
import com.da.common.enums.ResultEnum;
import com.da.common.exception.BusinessException;
import com.da.common.exception.ParameterException;
import com.da.common.utils.PBKDF2Util;
import com.da.common.utils.SnowflakeIdWorker;
import com.da.common.utils.TimestampUtil;
import com.da.auth.convert.DailyUserConverter;
import com.da.auth.entity.DailySaltUser;
import com.da.auth.entity.DailyUserRoles;
import com.da.auth.entity.DailyUsers;
import com.da.auth.entity.dto.DailyUsersDTO;
import com.da.auth.mapper.CommonMapper;
import com.da.auth.mapper.DailySaltUserMapper;
import com.da.auth.mapper.DailyUserRolesMapper;
import com.da.auth.mapper.DailyUsersMapper;
import com.da.auth.service.DailyUserService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;

/**
 * @Author: hyacinth
 * @CreateTime: 2025-01-10
 * @Version: 1.0
 */
@Slf4j
@Service
public class DailyUserServiceImpl implements DailyUserService {

    private final DailyUsersMapper dailyUsersMapper;
    private final DailySaltUserMapper dailySaltUserMapper;
    private final ThreadPoolTaskExecutor threadPoolTaskExecutor;
    private final DailyUserRolesMapper dailyUserRolesMapper;

    private final PlatformTransactionManager transactionManager;
    private final CommonMapper<?> commonMapper;
    @Resource
    private  PasswordEncoder passwordEncoder;


    public DailyUserServiceImpl(DailyUsersMapper dailyUsersMapper, DailySaltUserMapper dailySaltUserMapper
            , ThreadPoolTaskExecutor threadPoolTaskExecutor, PlatformTransactionManager transactionManager,
                                CommonMapper<?> commonMapper, DailyUserRolesMapper dailyUserRolesMapper) {
        this.dailyUsersMapper = dailyUsersMapper;
        this.dailySaltUserMapper = dailySaltUserMapper;
        this.threadPoolTaskExecutor = threadPoolTaskExecutor;
        this.transactionManager = transactionManager;
        this.commonMapper = commonMapper;
        this.dailyUserRolesMapper = dailyUserRolesMapper;
    }

    /**
     * 创建用户
     *
     * @param dailyUsersDTO
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public Boolean createUser(DailyUsersDTO dailyUsersDTO) {
        int count = commonMapper.queryCountByCondition("daily_users", "username", dailyUsersDTO.getUsername());
        if (count > 0) {
            throw new BusinessException(ResultEnum.FAIL.getCode(), "用户名称已存在,请更换其他名称！");
        }

        int count1 = commonMapper.queryCountByCondition("daily_users", "email", dailyUsersDTO.getEmail());
        if (count1 > 2) {
            throw new BusinessException(ResultEnum.FAIL.getCode(), "该邮箱已绑定三个账号,无法再绑定其他账号,如有需要请解绑其他账号");
        }

        DailyUsers dailyUsers = DailyUserConverter.INSTANCE.convertDTOToEntity(dailyUsersDTO);
        long snowFlakeId = SnowflakeIdWorker.generateId();
        String id = String.valueOf(snowFlakeId);
        dailyUsers.setId(id);
        // 密码加密
        String password = dailyUsersDTO.getPassword();
        String encryptPassword = passwordEncoder.encode(password);
        dailyUsers.setPassword(encryptPassword);
        // 手机号加密
        String phoneNumber = dailyUsersDTO.getPhoneNumber();
        String maskPhone = passwordEncoder.encode(phoneNumber);
        dailyUsers.setPhoneNumber(maskPhone);
        Date createAt = TimestampUtil.now();
        dailyUsers.setCreatedAt(createAt);
        dailyUsers.setStatus(DailyConstant.ACTIVE);

        try {
            int isCreateDailyUser = dailyUsersMapper.createDailyUser(dailyUsers);
            //关联用户角色
            DailyUserRoles dailyUserRoles = new DailyUserRoles();
            if (StringUtils.isBlank(dailyUsersDTO.getRoleId())) {
                dailyUserRoles.setId(String.valueOf(SnowflakeIdWorker.generateId()));
                dailyUserRoles.setRoleId(DailyAuthConstant.PT_ROLE_ID);
                dailyUserRoles.setUserId(dailyUsers.getId());
                dailyUserRoles.setCreatedTime(createAt);
                dailyUserRolesMapper.insert(dailyUserRoles);
            } else {
                dailyUserRoles.setId(String.valueOf(SnowflakeIdWorker.generateId()));
                dailyUserRoles.setRoleId(dailyUsersDTO.getRoleId());
                dailyUserRoles.setUserId(dailyUsers.getId());
                dailyUserRoles.setCreatedTime(createAt);
                dailyUserRolesMapper.insert(dailyUserRoles);
            }
            return isCreateDailyUser > 0;
        } catch (Exception e) {
            log.error("新增用户失败:{}", e.getMessage());
            throw new BusinessException(ResultEnum.FAIL.getCode(), e.getMessage());
        }
    }

    /**
     * 查询所有用户
     *
     * @return
     */
    public PageResult<DailyUsers> getPageByAllUsers(int pageNum, int pageSize) {
        // 计算偏移量
        int offset = (pageNum - 1) * pageSize;
        List<DailyUsers> all = dailyUsersMapper.selectPage(offset, pageSize);
        long total = dailyUsersMapper.selectCount();
        return new PageResult<>(pageNum, pageSize, total, all);
    }

    /**
     * 根据id查询用户
     *
     * @param id
     * @return
     */
    @Override
    public DailyUsers getUserById(String id) {
        return dailyUsersMapper.selectById(id);
    }

    /**
     * 根据id删除用户
     *
     * @param id 用户id
     * @return
     * @throws BusinessException
     */
    @Override
    @Transactional
    public Boolean deleteUser(String id) throws BusinessException {
        DailyUsers dailyUsers = dailyUsersMapper.selectById(id);
        Optional.ofNullable(dailyUsers).orElseThrow(() -> new IllegalArgumentException("未查询到对于id为:" + id + "的用户"));
        try {
            int isDeletedUser = dailyUsersMapper.deleteById(id);
            List<DailyUserRoles> dailyUserRolesIdList = dailyUserRolesMapper.queryListByUserId(id);
            dailyUserRolesMapper.deleteBatchIds(dailyUserRolesIdList);
            return isDeletedUser > 0;
        } catch (Exception e) {
            log.error("删除用户失败:{}", e.getMessage());
            throw new BusinessException(ResultEnum.FAIL.getCode(), e.getMessage());
        }

    }

    /**
     * 修改用户
     *
     * @param dailyUsersDTO 用户信息
     * @return
     * @throws ParameterException
     * @throws BusinessException
     */
    @Override
    public Boolean updateUser(DailyUsersDTO dailyUsersDTO) throws ParameterException, BusinessException {
        DailyUsers dailyUsers = DailyUserConverter.INSTANCE.convertDTOToEntity(dailyUsersDTO);
        String id = dailyUsers.getId();
        Optional.ofNullable(id).orElseThrow(() -> new ParameterException(ResultEnum.FAIL.getCode(), "id不能为空!"));
        DailyUsers dailyUser = dailyUsersMapper.selectById(id);
        Optional.ofNullable(dailyUser).orElseThrow(() -> new IllegalArgumentException("未查询到对于id为:" + id + "的用户"));
        Date updatedAt = new Date();
        dailyUsers.setUpdatedAt(updatedAt);
        try {
            int isUpdateUser = dailyUsersMapper.updateById(dailyUsers);
            return isUpdateUser > 0;
        } catch (Exception e) {
            log.error("修改用户失败:{}", e.getMessage());
            throw new BusinessException(ResultEnum.FAIL.getCode(), e.getMessage());
        }
    }

    /**
     * 批量新增用户
     *
     * @param dailyUsersList 用户列表
     * @return
     */
    @Override
    public Future<Boolean> batchAddUser(List<DailyUsers> dailyUsersList) {
        int batchSize = 100; // 每批次处理的数据量
        List<Callable<Boolean>> tasks = new LinkedList<>();
        List<DailyUsers> list = new ArrayList<>();
        // 分批处理用户数据
        for (int i = 0; i < dailyUsersList.size(); i += batchSize) {
            int toIndex = Math.min(i + batchSize, dailyUsersList.size());
            List<DailyUsers> usersList = dailyUsersList.subList(i, toIndex);
            for (DailyUsers dailyUsers : usersList) {
                DailyUsers dailyUser = new DailyUsers();
                // 检查用户名是否已存在
                String username = dailyUsers.getUsername();
                int existingUserCount = dailyUsersMapper.queryCountyByUserName(username);
                if (existingUserCount > 0) {
                    String phoneNumber = dailyUsers.getPhoneNumber();
                    dailyUser.setUsername("daily_" + phoneNumber); // 如果用户名已存在，使用前缀+手机号作为用户名
                } else {
                    dailyUser.setUsername(dailyUsers.getUsername());
                }
                dailyUser.setId(String.valueOf(SnowflakeIdWorker.generateId()));
                dailyUser.setStatus(DailyConstant.ACTIVE);
                dailyUser.setCreatedAt(TimestampUtil.now());
                dailyUser.setPassword(dailyUsers.getPassword());
                dailyUser.setPhoneNumber(dailyUsers.getPhoneNumber());

            }
            // 打印日志，检查数据是否正确组装
            log.info("准备插入的用户数据: {}", list);
            // 提交任务到线程池
            tasks.add(() -> {
                TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
                try {
                    dailyUsersMapper.batchInsert(list);
                    transactionManager.commit(status); // 提交事务
                    log.info("批量插入完成");
                    return true;
                } catch (Exception e) {
                    transactionManager.rollback(status); // 回滚事务
                    log.error("批量插入失败", e); // 打印堆栈信息
                    throw e;
                }
            });
        }

        // 提交所有任务并返回Future
        return threadPoolTaskExecutor.submit(() -> {
            System.out.println("--------------------------------------");
            TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
            try {
                System.out.println("--执行任务--");
                threadPoolTaskExecutor.getThreadPoolExecutor().invokeAll(tasks);
                System.out.println("--执行任务后--");
                transactionManager.commit(status); // 手动提交事务
                return true;
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                transactionManager.rollback(status); // 回滚事务
                throw new RuntimeException("多线程批量导入被中断", e);
            } finally {
                log.info("-------------关闭线程------------");
                threadPoolTaskExecutor.shutdown(); // 关闭线程池
            }
        });
    }

    /**
     * 批量删除用户数据
     *
     * @param dailyUsersIdList 用户id列表
     * @return
     */
    @Override
    public Boolean batchDeletedUser(List<String> dailyUsersIdList) {
        int batchSize = 100;
        int totalDeleted = 0;
        for (int i = 0; i < dailyUsersIdList.size(); i += batchSize) {
            int toIndex = Math.min(i + batchSize, dailyUsersIdList.size());
            List<String> batchIds = dailyUsersIdList.subList(i, toIndex);
            try {
                int deletedCount = dailyUsersMapper.deleteBatchIds(batchIds);
                totalDeleted += deletedCount;
                log.info("成功删除第 {} 批次用户数据，数量: {}", (i / batchSize) + 1, deletedCount);
            } catch (Exception e) {
                log.error("删除第 {} 批次用户数据失败: {}", (i / batchSize) + 1, e.getMessage(), e);
                throw new BusinessException(ResultEnum.FAIL.getCode(), "删除用户数据失败: " + e.getMessage());
            }
        }
        log.info("批量删除用户数据完成，总删除数量: {}", totalDeleted);
        return true;
    }


}
